home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / dev / c / qtools0.2-src.lha / src / libqtools / TDDD.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-07-16  |  35.8 KB  |  1,221 lines

  1. #define    LIBQTOOLS_CORE
  2. #include "../include/libqtools.h"
  3. #include "../include/libqbuild.h"
  4. #include "TDDD.h"
  5.  
  6. #define    CLUSTER_POINTS        (CLUSTER_FACES / 3)
  7. #define    CLUSTER_GROUPS        16
  8. #define    CLUSTER_SUBGROUP    (CLUSTER_FACES / 3)
  9.  
  10. int TDDDmax_pcount = 0;
  11. int TDDDmax_ecount = 0;
  12. int TDDDmax_tcount = 0;
  13. int TDDDmax_gcount = 0;
  14. struct points *TDDDpoints = 0;
  15. struct edges *TDDDedges = 0;
  16. struct faces *TDDDfaces = 0;
  17. int TDDDgroups = 0;
  18. int *TDDDgroupsizes = 0;
  19. struct facesubgroup **TDDDgroup = 0;
  20. struct brush5 *TDDDbrushes = 0;
  21.  
  22. int TDDDnumpoints = 0;
  23. int TDDDnumedges = 0;
  24. int TDDDnumfaces = 0;
  25. int TDDDnumgroups = 0;
  26. int TDDDnumobjects = 0;
  27.  
  28. int nummapbrushes;                        /* 4 */
  29.  
  30. void AllocTDDDSubGroup(register unsigned short int faceNum, register char *texname)
  31. {
  32.   unsigned short int i, j;
  33.  
  34. #if    (WORDS_BIGENDIAN == 0)
  35.   faceNum = BigShort(faceNum);
  36. #endif
  37.  
  38.   if (!TDDDgroup) {
  39.     if (!(TDDDgroup = (struct facesubgroup **)tmalloc(CLUSTER_GROUPS * sizeof(struct facesubgroup *))))
  40.         Error(failed_memoryunsize, "group");
  41.     if (!(TDDDgroupsizes = (int *)tmalloc(CLUSTER_GROUPS * sizeof(int))))
  42.         Error(failed_memoryunsize, "group");
  43.     if (!(TDDDbrushes = (struct brush5 *)tmalloc(CLUSTER_GROUPS * sizeof(struct brush5))))
  44.         Error(failed_memoryunsize, "brush");
  45.   }
  46.  
  47.   if (TDDDgroups >= TDDDmax_gcount) {
  48.     if (!(TDDDgroup = (struct facesubgroup **)trealloc(TDDDgroup, ((TDDDmax_gcount += CLUSTER_GROUPS) * sizeof(struct facesubgroup *)))))
  49.         Error(failed_memoryunsize, "group");
  50.     if (!(TDDDgroupsizes = (int *)trealloc(TDDDgroupsizes, (TDDDmax_gcount * sizeof(int)))))
  51.         Error(failed_memoryunsize, "group");
  52.     if (!(TDDDbrushes = (struct brush5 *)trealloc(TDDDbrushes, (TDDDmax_gcount * sizeof(struct brush5)))))
  53.         Error(failed_memoryunsize, "brush");
  54.   }
  55.  
  56.   for (i = 0; i < TDDDgroups; i++)
  57.     if (!__strncmp(TDDDgroup[i]->name, texname, 18))
  58.       break;
  59.  
  60.   if (!TDDDgroup[i])
  61.     if (!(TDDDgroup[i] = (struct facesubgroup *)tmalloc((CLUSTER_SUBGROUP * sizeof(unsigned short int)) + sizeof(struct facesubgroup))))
  62.         Error(failed_memoryunsize, "subgroup");
  63.  
  64.   if (TDDDgroup[i]->count >= TDDDgroupsizes[i])
  65.     if (!(TDDDgroup[i] = (struct facesubgroup *)trealloc(TDDDgroup[i], ((TDDDgroupsizes[i] += CLUSTER_SUBGROUP) * sizeof(unsigned short int)) + sizeof(struct facesubgroup))))
  66.         Error(failed_memoryunsize, "subgroup");
  67.  
  68.   if (i == TDDDgroups) {
  69.     __strncpy(TDDDgroup[i]->name, texname, 18);
  70.     TDDDbrushes[i].fullscale = BigShort(1);
  71.     TDDDbrushes[i].flags = BigShort(BRS_COLOR);
  72.     TDDDbrushes[i].wflags = BigShort(BRW_REPEA);
  73.     TDDDgroups++;
  74.     TDDDnumgroups++;
  75.   }
  76.  
  77.   for (j = 0; j < TDDDgroup[i]->count; j++)
  78.     if (faceNum == TDDDgroup[i]->facelist[j])
  79.       return;
  80.  
  81.   TDDDgroup[i]->facelist[j] = faceNum;
  82.   TDDDgroup[i]->count++;
  83. }
  84.  
  85. unsigned short int AllocTDDDPoint(register vector * point)
  86. {
  87.   unsigned short int i;
  88.  
  89. #if    (WORDS_BIGENDIAN == 0)
  90.   point->x = BigLong(point->x);
  91.   point->y = BigLong(point->y);
  92.   point->z = BigLong(point->z);
  93. #endif
  94.  
  95.   if (!TDDDpoints)
  96.     if (!(TDDDpoints = (struct points *)tmalloc((CLUSTER_POINTS * sizeof(vector)) + sizeof(struct points))))
  97.         Error(failed_memoryunsize, "point");
  98.  
  99.   if (TDDDpoints->pcount >= TDDDmax_pcount)
  100.     if (!(TDDDpoints = (struct points *)trealloc(TDDDpoints, ((TDDDmax_pcount += CLUSTER_POINTS) * sizeof(vector)) + sizeof(struct points))))
  101.         Error(failed_memoryunsize, "point");
  102.  
  103.   for (i = 0; i < TDDDpoints->pcount; i++) {
  104.     if (point->x == TDDDpoints->points[i].x)
  105.       if (point->y == TDDDpoints->points[i].y)
  106.     if (point->z == TDDDpoints->points[i].z)
  107.       return i;
  108.   }
  109.   TDDDpoints->points[i].x = point->x;
  110.   TDDDpoints->points[i].y = point->y;
  111.   TDDDpoints->points[i].z = point->z;
  112.   TDDDpoints->pcount++;
  113.   TDDDnumpoints++;
  114.  
  115.   return i;
  116. }
  117.  
  118. unsigned short int AllocTDDDEdge(register unsigned short int point0, register unsigned short int point1)
  119. {
  120.   unsigned short int i;
  121.  
  122. #if    (WORDS_BIGENDIAN == 0)
  123.   point0 = BigShort(point0);
  124.   point1 = BigShort(point1);
  125. #endif
  126.  
  127.   if (!TDDDedges)
  128.     if (!(TDDDedges = (struct edges *)tmalloc((CLUSTER_EDGES * sizeof(unsigned short int) * 2) + sizeof(struct edges))))
  129.         Error(failed_memoryunsize, "edge");
  130.  
  131.   if (TDDDedges->ecount >= TDDDmax_ecount)
  132.     if (!(TDDDedges = (struct edges *)trealloc(TDDDedges, ((TDDDmax_ecount += CLUSTER_EDGES) * sizeof(unsigned short int) * 2) + sizeof(struct edges))))
  133.         Error(failed_memoryunsize, "edge");
  134.  
  135.   for (i = 0; i < TDDDedges->ecount; i++) {
  136.     if (point0 == TDDDedges->edges[i][0])
  137.       if (point1 == TDDDedges->edges[i][1])
  138.     return i;
  139.   }
  140.   TDDDedges->edges[i][0] = point0;
  141.   TDDDedges->edges[i][1] = point1;
  142.   TDDDedges->ecount++;
  143.   TDDDnumedges++;
  144.   return i;
  145. }
  146.  
  147. unsigned short int AllocTDDDFace(register unsigned short int connect0, register unsigned short int connect1, register unsigned short int connect2)
  148. {
  149.   unsigned short int i;
  150.  
  151. #if    (WORDS_BIGENDIAN == 0)
  152.   connect0 = BigShort(connect0);
  153.   connect1 = BigShort(connect1);
  154.   connect2 = BigShort(connect2);
  155. #endif
  156.  
  157.   if (!TDDDfaces)
  158.     if (!(TDDDfaces = (struct faces *)tmalloc((CLUSTER_FACES * sizeof(unsigned short int) * 3) + sizeof(struct faces))))
  159.         Error(failed_memoryunsize, "face");
  160.  
  161.   if (TDDDfaces->tcount >= TDDDmax_tcount)
  162.     if (!(TDDDfaces = (struct faces *)trealloc(TDDDfaces, ((TDDDmax_tcount += CLUSTER_FACES) * sizeof(unsigned short int) * 3) + sizeof(struct faces))))
  163.         Error(failed_memoryunsize, "face");
  164.  
  165.   for (i = 0; i < TDDDfaces->tcount; i++) {
  166.     if (connect0 == TDDDfaces->connects[i][0])
  167.       if (connect1 == TDDDfaces->connects[i][1])
  168.     if (connect2 == TDDDfaces->connects[i][2])
  169.       return i;
  170.   }
  171.   TDDDfaces->connects[i][0] = connect0;
  172.   TDDDfaces->connects[i][1] = connect1;
  173.   TDDDfaces->connects[i][2] = connect2;
  174.   TDDDfaces->tcount++;
  175.   TDDDnumfaces++;
  176.   return i;
  177. }
  178.  
  179. bool SaveFace(vec3_t point0, vec3_t point1, vec3_t point2, register char *texname)
  180. {
  181.   unsigned short int face, p0, p1, p2;
  182.   vector p;
  183.  
  184.   p.x = float2fract(point0[0]);
  185.   p.y = float2fract(point0[1]);
  186.   p.z = float2fract(point0[2]);
  187.   p0 = AllocTDDDPoint(&p);
  188.   p.x = float2fract(point1[0]);
  189.   p.y = float2fract(point1[1]);
  190.   p.z = float2fract(point1[2]);
  191.   p1 = AllocTDDDPoint(&p);
  192.   p.x = float2fract(point2[0]);
  193.   p.y = float2fract(point2[1]);
  194.   p.z = float2fract(point2[2]);
  195.   p2 = AllocTDDDPoint(&p);
  196.  
  197.   face = AllocTDDDFace(AllocTDDDEdge(p0, p1),
  198.                AllocTDDDEdge(p1, p2),
  199.                AllocTDDDEdge(p2, p0));
  200.   AllocTDDDSubGroup(face, texname);
  201.   return TRUE;
  202. }
  203.  
  204. bool SetForm(register HANDLE outFile, register int *last, register int ID)
  205. {
  206.   int Form[3];
  207.   
  208.   Form[0] = BigLong(ID_FORM);
  209.   Form[1] = BigLong(*last);
  210.   Form[2] = BigLong(ID);
  211.  
  212.   *last = __ltell(outFile) + 8;
  213.   __write(outFile, Form, 12);
  214.  
  215.   return TRUE;
  216. }
  217.  
  218. bool SetRoot(register HANDLE outFile, register int *last, register int ID)
  219. {
  220.   int Root[2];
  221.   
  222.   Root[0] = BigLong(ID);
  223.   Root[1] = BigLong(*last);
  224.   
  225.   *last = __ltell(outFile) + 8;
  226.   __write(outFile, Root, 8);
  227.  
  228.   return TRUE;
  229. }
  230.  
  231. bool SetEndM(register HANDLE outFile, register int ID)
  232. {
  233.   int EndM[2];
  234.   
  235.   EndM[0] = BigLong(ID);
  236.   EndM[1] = BigLong(0);
  237.  
  238.   __write(outFile, EndM, 8);
  239.   TDDDnumobjects++;
  240.  
  241.   return TRUE;
  242. }
  243.  
  244. bool VerRoot(register HANDLE outFile, register int *last, register int ID)
  245. {
  246.   int this = __ltell(outFile);
  247.   int Root[2];
  248.  
  249.   __lseek(outFile, *last - 8, SEEK_SET);
  250.   *last = this - *last;
  251.   
  252.   Root[0] = BigLong(ID);
  253.   Root[1] = BigLong(*last);
  254.  
  255.   __write(outFile, Root, 8);
  256.   __lseek(outFile, this, SEEK_SET);
  257.  
  258.   return TRUE;
  259. }
  260.  
  261. bool SetClassName(register HANDLE outFile, register char *className)
  262. {
  263.   int Class[2];
  264.   
  265.   Class[0] = BigLong(ID_NAME);
  266.   Class[1] = BigLong(18);
  267.  
  268.   __write(outFile, Class, 8);
  269.   __write(outFile, className, __strlen(className));
  270.  
  271.   return TRUE;
  272. }
  273.  
  274. bool SetEntity(register HANDLE outFile, register char *variable, register char *content)
  275. {
  276.   int nameLen = __strlen(content);
  277.   struct {
  278.     int Entity[2];
  279.     struct texture4 brushTex;
  280.   } ent;
  281.  
  282.   nameLen = ((nameLen + 1) & ~1);
  283.   nameLen++;
  284.   nameLen = ((nameLen + 1) & ~1);
  285.   __bzero(&ent.brushTex, sizeof(struct texture4));
  286.   __strncpy(ent.brushTex.label, variable, 18 + 1);
  287.  
  288.   ent.Entity[0] = BigLong(ID_TXT4);
  289.   ent.Entity[1] = BigLong(sizeof(struct texture4) + nameLen);
  290.   ent.brushTex.flags = BigShort(TXT_DISAB);
  291.   ent.brushTex.length = (char)nameLen;
  292.  
  293.   __write(outFile, &ent, 8 + sizeof(struct texture4));
  294.   __write(outFile, content, nameLen - 1);
  295.   __write(outFile, "\0", 1);
  296.  
  297.   return TRUE;
  298. }
  299.  
  300. bool SetBrushes(register HANDLE outFile)
  301. {
  302.   int lastBrush, i;
  303.  
  304.   for (i = 0; i < TDDDgroups; i++) {
  305.     /*
  306.      * write only a subgroup if there are more than one
  307.      * and if the subgroup contains members
  308.      */
  309.     if ((TDDDgroups > 1) && (TDDDgroup[i]->count > 0)) {
  310.       SetRoot(outFile, &lastBrush, ID_FGRP);
  311.       __write(outFile, TDDDgroup[i], 20 + (sizeof(unsigned short int) * TDDDgroup[i]->count));
  312.  
  313.       VerRoot(outFile, &lastBrush, ID_FGRP);
  314.       __strncpy(TDDDbrushes[i].subgrp, TDDDgroup[i]->name, 18);
  315.     }
  316.     SetRoot(outFile, &lastBrush, ID_BRS5);
  317.     TDDDbrushes[i].length = ((__strlen(TDDDgroup[i]->name + 1) + 1) & ~1);
  318.     __write(outFile, &TDDDbrushes[i], sizeof(struct brush5));
  319.  
  320.     __write(outFile, TDDDgroup[i]->name, TDDDbrushes[i].length);
  321.     VerRoot(outFile, &lastBrush, ID_BRS5);
  322.     TDDDgroup[i]->count = 0;
  323.   }
  324.   TDDDgroups = 0;
  325.  
  326.   return TRUE;
  327. }
  328.  
  329. bool SetPoints(register HANDLE outFile)
  330. {
  331.   if (TDDDpoints) {
  332.     if (TDDDpoints->pcount) {
  333.       int len = (sizeof(vector) * TDDDpoints->pcount) + sizeof(unsigned short int);
  334.       int Points[2];
  335.  
  336.       Points[0] = BigLong(ID_PNTS);
  337.       Points[1] = BigLong(len);
  338.  
  339.       __write(outFile, Points, 8);
  340.       __write(outFile, TDDDpoints, len);
  341.  
  342.       TDDDpoints->pcount = 0;
  343.     }
  344.   }
  345.   return TRUE;
  346. }
  347.  
  348. bool SetEdges(register HANDLE outFile)
  349. {
  350.   if (TDDDedges) {
  351.     if (TDDDedges->ecount) {
  352.       int len = sizeof(unsigned short int) * ((TDDDedges->ecount * 2) + 1);
  353.       int Edges[2];
  354.       
  355.       Edges[0] = BigLong(ID_EDGE);
  356.       Edges[1] = BigLong(len);
  357.  
  358.       __write(outFile, Edges, 8);
  359.       __write(outFile, TDDDedges, len);
  360.  
  361.       TDDDedges->ecount = 0;
  362.     }
  363.   }
  364.   return TRUE;
  365. }
  366.  
  367. bool SetFaces(register HANDLE outFile)
  368. {
  369.   if (TDDDfaces) {
  370.     if (TDDDfaces->tcount) {
  371.       int len = sizeof(unsigned short int) * ((TDDDfaces->tcount * 3) + 1);
  372.       int Faces[2];
  373.       
  374.       Faces[0] = BigLong(ID_FACE);
  375.       Faces[1] = BigLong(len);
  376.  
  377.       __write(outFile, Faces, 8);
  378.       __write(outFile, TDDDfaces, len);
  379.  
  380.       TDDDfaces->tcount = 0;
  381.     }
  382.   }
  383.   return TRUE;
  384. }
  385.  
  386. bool SetOtherDefaults(register HANDLE outFile, register struct entity * ent)
  387. {
  388.   double posx = 0;
  389.   double posy = 0;
  390.   double posz = 0;
  391.   int points, len, i;
  392.   struct axis axis =
  393.   {
  394.     {0x00010000, 0x00000000, 0x00000000},
  395.     {0x00000000, 0x00010000, 0x00000000},
  396.     {0x00000000, 0x00000000, 0x00010000}};
  397.   struct posi position =
  398.   {
  399.     {0, 0, 0}};
  400.   struct shap shape;
  401.   struct colr colour;
  402.   int Defs[2];
  403.  
  404.   axis.xaxis.x = axis.yaxis.y = axis.zaxis.z = BigLong(0x00010000);
  405.   shape.shape = BigShort(SH_AXIS);
  406.   shape.lamp = BigShort(LP2_NOLAM);
  407.  
  408.   if (ent) {
  409.     position.position.x = float2fract(ent->origin[0]);
  410.     position.position.y = float2fract(ent->origin[1]);
  411.     position.position.z = float2fract(ent->origin[2]);
  412.     if (ent->style) {
  413.       struct {
  414.         int Light[2];
  415.         struct int1 light;
  416.       } lit;
  417.  
  418.       shape.lamp = BigShort(LP2_POINT);
  419.  
  420.       lit.Light[0] = BigLong(ID_INT1);
  421.       lit.Light[1] = BigLong(sizeof(struct int1));
  422.       lit.light.intensity.x = lit.light.intensity.y = lit.light.intensity.z = BigFloat(((unsigned int)ent->light << 22) / 75);
  423.  
  424.       __write(outFile, &lit, 8 + sizeof(struct int1));
  425.     }
  426.   }
  427.  
  428.   if (TDDDpoints)
  429.     if (TDDDpoints->pcount) {
  430.       struct {
  431.         int Attr[2];
  432.         struct bbox bound;
  433.       } att;
  434.       struct faceattr *attr = (struct faceattr *)tmalloc((TDDDfaces->tcount * sizeof(rgb)) + sizeof(struct faceattr));
  435.  
  436.       att.bound.maxs.x = att.bound.maxs.y = att.bound.maxs.z = 0x80000000;
  437.       att.bound.mins.x = att.bound.mins.y = att.bound.mins.z = 0x7FFFFFFF;
  438.  
  439.       for (points = 0; points < TDDDpoints->pcount; points++) {
  440.     if (TDDDpoints->points[points].x > att.bound.maxs.x)
  441.       att.bound.maxs.x = TDDDpoints->points[points].x;
  442.     else if (TDDDpoints->points[points].x < att.bound.mins.x)
  443.       att.bound.mins.x = TDDDpoints->points[points].x;
  444.     if (TDDDpoints->points[points].y > att.bound.maxs.y)
  445.       att.bound.maxs.y = TDDDpoints->points[points].y;
  446.     else if (TDDDpoints->points[points].y < att.bound.mins.y)
  447.       att.bound.mins.y = TDDDpoints->points[points].y;
  448.     if (TDDDpoints->points[points].z > att.bound.maxs.z)
  449.       att.bound.maxs.z = TDDDpoints->points[points].z;
  450.     else if (TDDDpoints->points[points].z < att.bound.mins.z)
  451.       att.bound.mins.z = TDDDpoints->points[points].z;
  452.     posx += fract2float(TDDDpoints->points[points].x);
  453.     posy += fract2float(TDDDpoints->points[points].y);
  454.     posz += fract2float(TDDDpoints->points[points].z);
  455.       }
  456.       position.position.x = BigLong(float2fract(posx / TDDDpoints->pcount));
  457.       position.position.y = BigLong(float2fract(posy / TDDDpoints->pcount));
  458.       position.position.z = BigLong(float2fract(posz / TDDDpoints->pcount));
  459.  
  460.       att.Attr[0] = BigLong(ID_BBOX);
  461.       att.Attr[1] = BigLong(sizeof(struct bbox));
  462.       att.bound.maxs.x = BigLong(att.bound.maxs.x - BigLong(position.position.x));
  463.       att.bound.maxs.y = BigLong(att.bound.maxs.y - BigLong(position.position.y));
  464.       att.bound.maxs.z = BigLong(att.bound.maxs.z - BigLong(position.position.z));
  465.       att.bound.mins.x = BigLong(att.bound.mins.x - BigLong(position.position.x));
  466.       att.bound.mins.y = BigLong(att.bound.mins.y - BigLong(position.position.y));
  467.       att.bound.mins.z = BigLong(att.bound.mins.z - BigLong(position.position.z));
  468.  
  469.       __write(outFile, &att, 8 + sizeof(struct bbox));
  470.  
  471.       attr->count = BigShort(TDDDfaces->tcount);
  472.       for (i = 0; i < TDDDfaces->tcount; i++) {
  473.     attr->attr[i].r = 0xFF;
  474.     attr->attr[i].g = 0xFF;
  475.     attr->attr[i].b = 0xFF;
  476.       }
  477.       len = (TDDDfaces->tcount * sizeof(rgb)) + sizeof(unsigned short int);
  478.       len = ((len + 1) & ~1);
  479.       att.Attr[1] = BigLong(len);
  480.       
  481.       att.Attr[0] = BigLong(ID_CLST);
  482.       __write(outFile, att.Attr, 8);
  483.       __write(outFile, &attr, len);
  484.       att.Attr[0] = BigLong(ID_RLST);
  485.       __write(outFile, att.Attr, 8);
  486.       __write(outFile, &attr, len);
  487.       att.Attr[0] = BigLong(ID_TLST);
  488.       __write(outFile, att.Attr, 8);
  489.       __write(outFile, &attr, len);
  490.  
  491.       tfree(attr);
  492.     }
  493.  
  494.   Defs[0] = BigLong(ID_AXIS);
  495.   Defs[1] = BigLong(sizeof(struct axis));
  496.   __write(outFile, Defs, 8);
  497.   __write(outFile, &axis, sizeof(struct axis));
  498.  
  499.   Defs[0] = BigLong(ID_POSI);
  500.   Defs[1] = BigLong(sizeof(struct posi));
  501.   __write(outFile, Defs, 8);
  502.   __write(outFile, &position, sizeof(struct posi));
  503.  
  504.   Defs[0] = BigLong(ID_SHP2);
  505.   Defs[1] = BigLong(sizeof(struct shap));
  506.   __write(outFile, Defs, 8);
  507.   __write(outFile, &shape, sizeof(struct shap));
  508.  
  509.   colour.color = 0x00FFFFFF;
  510.   Defs[1] = BigLong(sizeof(struct colr));
  511.  
  512.   Defs[0] = BigLong(ID_COLR);
  513.   __write(outFile, Defs, 8);
  514.   __write(outFile, &colour, sizeof(struct colr));
  515.   Defs[0] = BigLong(ID_REFL);
  516.   __write(outFile, Defs, 8);
  517.   __write(outFile, &colour, sizeof(struct colr));
  518.   Defs[0] = BigLong(ID_TRAN);
  519.   __write(outFile, Defs, 8);
  520.   __write(outFile, &colour, sizeof(struct colr));
  521.   Defs[0] = BigLong(ID_SPC1);
  522.   __write(outFile, Defs, 8);
  523.   __write(outFile, &colour, sizeof(struct colr));
  524.  
  525.   return TRUE;
  526. }
  527.  
  528. /*
  529.  * convert a Imagine-TDDD to a Quake-Map
  530.  */
  531.  
  532. /* IFF to pseudo IFF */
  533. int fileIFFtopIFF(HANDLE iobFile, struct IFFchunk *IFFroot);
  534. int memIFFtopIFF(unsigned char *iobMem, struct IFFchunk *IFFroot);
  535.  
  536. /* pseudo IFF to pseudo Brushes */
  537. void pIFFtopBrushes(__memBase, struct IFFchunk *IFFroot, int iterVal, struct entity *fillEntity);
  538.  
  539. /* pseudo IFF to pseudo Map */
  540. void pIFFtopMap(__memBase, struct IFFchunk *IFFroot, int iterVal);
  541.  
  542. void strlwrcpy(register char *dst, register char *src)
  543. {
  544.   int i, len = __strlen(src);
  545.  
  546.   for (i = 0; i < len; i++)
  547.     dst[i] = (char)tolower((int)src[i]);
  548.   dst[i] = 0;
  549. }
  550.  
  551. int fileIFFtopIFF(register HANDLE iobFile, register struct IFFchunk *IFFroot)
  552. {
  553.   int processed = 0;
  554.  
  555.   /*
  556.    * small hack -> IFFroot->iter is IFFpart->next
  557.    */
  558.   struct IFFchunk *IFFpart = (struct IFFchunk *)&IFFroot->size;
  559.  
  560.   while (IFFpart->type != BigLong(ID_TOBJ)) {
  561.     int oldOffs;
  562.  
  563.     /*
  564.      * allocate IFFchunk
  565.      */
  566.     IFFpart->next = (struct IFFchunk *)tmalloc(sizeof(struct IFFchunk));
  567.  
  568.     IFFpart = IFFpart->next;
  569.     IFFpart->next = 0;
  570.     IFFpart->iter = 0;
  571.     IFFpart->data = 0;
  572.  
  573.     /*
  574.      * read and parse IFFchunk
  575.      */
  576.     __read(iobFile, IFFpart, 8);
  577.     IFFpart->size = ((BigLong(IFFpart->size) + 1) & ~1);
  578.     processed += 8;
  579.     oldOffs = __ltell(iobFile);
  580.  
  581.     if (IFFpart->type == BigLong(ID_OBJ)) {
  582.       processed += fileIFFtopIFF(iobFile, IFFpart);
  583.       if ((IFFroot->type == BigLong(ID_TDDD)) && (IFFroot->size == processed))
  584.     break;
  585.     }
  586.     else if (IFFpart->type == BigLong(ID_DESC)) {
  587.       processed += fileIFFtopIFF(iobFile, IFFpart);
  588.       if ((IFFroot->type == BigLong(ID_OBJ)) && (IFFroot->size == processed))
  589.     break;
  590.     }
  591.     else if (IFFpart->type != BigLong(ID_TOBJ)) {
  592.       processed += IFFpart->size;
  593.       IFFpart->data = (void *)tmalloc(IFFpart->size + 1);
  594.       __read(iobFile, IFFpart->data, IFFpart->size);
  595.     }
  596.   }
  597.  
  598.   return processed;
  599. }
  600.  
  601. int memIFFtopIFF(register unsigned char *iobMem, register struct IFFchunk *IFFroot)
  602. {
  603.   int processed = 0;
  604.  
  605.   /*
  606.    * small hack -> IFFroot->iter is IFFpart->next
  607.    */
  608.   struct IFFchunk *IFFpart = (struct IFFchunk *)&IFFroot->size;
  609.  
  610.   while (IFFpart->type != BigLong(ID_TOBJ)) {
  611.     /*
  612.      * allocate IFFchunk
  613.      */
  614.     IFFpart->next = (struct IFFchunk *)tmalloc(sizeof(struct IFFchunk));
  615.  
  616.     IFFpart = IFFpart->next;
  617.     IFFpart->next = 0;
  618.     IFFpart->iter = 0;
  619.     IFFpart->data = 0;
  620.  
  621.     /*
  622.      * read and parse IFFchunk
  623.      */
  624.     __memcpy(IFFpart, iobMem, 8);
  625.     iobMem += 8;
  626.     IFFpart->size = ((BigLong(IFFpart->size) + 1) & ~1);
  627.     processed += 8;
  628.  
  629.     if (IFFpart->type == BigLong(ID_OBJ)) {
  630.       processed += memIFFtopIFF(iobMem, IFFpart);
  631.       if ((IFFroot->type == BigLong(ID_TDDD)) && (IFFroot->size == processed))
  632.     break;
  633.     }
  634.     else if (IFFpart->type == BigLong(ID_DESC)) {
  635.       processed += memIFFtopIFF(iobMem, IFFpart);
  636.       if ((IFFroot->type == BigLong(ID_OBJ)) && (IFFroot->size == processed))
  637.     break;
  638.     }
  639.     else if (IFFpart->type != BigLong(ID_TOBJ)) {
  640.       processed += IFFpart->size;
  641.       IFFpart->data = (void *)tmalloc(IFFpart->size + 1);
  642.       __memcpy(IFFpart->data, iobMem, IFFpart->size);
  643.       iobMem += IFFpart->size;
  644.     }
  645.   }
  646.  
  647.   return processed;
  648. }
  649.  
  650. void pIFFtopBrushes(__memBase, register struct IFFchunk *IFFroot, register int iterVal, register struct entity *fillEntity)
  651. {
  652.   struct IFFchunk *IFFpart = IFFroot;
  653.  
  654.   struct faces *facelist = 0;
  655.   struct posi *origin = 0;
  656.   struct edges *edgelist = 0;
  657.   struct points *pointlist = 0;
  658.   struct brush5 **brushtex = (struct brush5 **)tmalloc(15 * sizeof(struct brush5 *));
  659.   int brushtexs = 0;
  660.   struct facesubgroup **facegroup = (struct facesubgroup **)tmalloc(15 * sizeof(struct facesubgroup *));
  661.   int facegroups = 0;
  662.  
  663.   /*
  664.    * look for other iterated brushes
  665.    */
  666.   while (IFFpart) {
  667.     struct IFFchunk *actIFFpart = IFFpart;
  668.     int indentSpace = iterVal;
  669.  
  670.     while (indentSpace-- > 0) {
  671.       oprintf("  ");
  672.     }
  673.     oprintf("%4s %d bytes\n", (char *)&IFFpart->type, IFFpart->size);
  674.  
  675.     /*
  676.      * all types that are not DESC are for the actBrush
  677.      * after first appeareance of DESC there are only DESCs
  678.      */
  679.     switch (BigLong(IFFpart->type)) {
  680.       case ID_POSI:
  681.     origin = (struct posi *)actIFFpart->data;
  682.     break;
  683.       case ID_FACE:
  684.     facelist = (struct faces *)actIFFpart->data;
  685.     break;
  686.       case ID_EDGE:
  687.     edgelist = (struct edges *)actIFFpart->data;
  688.     break;
  689.       case ID_PNTS:
  690.     pointlist = (struct points *)actIFFpart->data;
  691.     break;
  692.       case ID_FGRP:
  693.       case ID_FGR2:
  694.       case ID_FGR3:
  695.       case ID_FGR4:
  696.     facegroup[facegroups] = (struct facesubgroup *)actIFFpart->data;
  697.     facegroups++;
  698.     break;
  699.       case ID_BRS5:
  700.     brushtex[brushtexs] = (struct brush5 *)actIFFpart->data;
  701.     brushtexs++;
  702.     break;
  703.       case ID_DESC:
  704.     pIFFtopBrushes(bspMem, actIFFpart->iter, iterVal + 1, fillEntity);
  705.     break;
  706.       default:
  707.     tfree(actIFFpart->data);
  708.     break;
  709.     }
  710.     IFFpart = IFFpart->next;
  711.     tfree(actIFFpart);
  712.   }
  713.  
  714.   if (facelist && edgelist && pointlist && brushtexs) {
  715.     int i;
  716.  
  717.     unsigned short int facecnt;
  718.     struct mbrush *actBrush = (struct mbrush *)tmalloc(sizeof(struct mbrush));
  719.     struct mface *checkFace = 0;
  720.     vec3_t middle;
  721.     unsigned short int p0, p1, p2;
  722.     vector *point;
  723.  
  724.     for (facecnt = 0; facecnt < BigShort(facelist->tcount); facecnt++) {
  725.       p0 = edgelist->edges[BigShort(facelist->connects[facecnt][0])][0];
  726.       p1 = edgelist->edges[BigShort(facelist->connects[facecnt][0])][1];
  727.       if ((edgelist->edges[BigShort(facelist->connects[facecnt][1])][0] != p0) &&
  728.       (edgelist->edges[BigShort(facelist->connects[facecnt][1])][0] != p1))
  729.     p2 = edgelist->edges[BigShort(facelist->connects[facecnt][1])][0];
  730.       else
  731.     p2 = edgelist->edges[BigShort(facelist->connects[facecnt][1])][1];
  732.  
  733.       point = &pointlist->points[BigShort(p0)];
  734.       middle[0] += fract2float(BigLong(point->x));
  735.       middle[1] += fract2float(BigLong(point->y));
  736.       middle[2] += fract2float(BigLong(point->z));
  737.       point = &pointlist->points[BigShort(p1)];
  738.       middle[0] += fract2float(BigLong(point->x));
  739.       middle[1] += fract2float(BigLong(point->y));
  740.       middle[2] += fract2float(BigLong(point->z));
  741.       point = &pointlist->points[BigShort(p2)];
  742.       middle[0] += fract2float(BigLong(point->x));
  743.       middle[1] += fract2float(BigLong(point->y));
  744.       middle[2] += fract2float(BigLong(point->z));
  745.     }
  746.     middle[0] /= (facecnt * 3);
  747.     middle[1] /= (facecnt * 3);
  748.     middle[2] /= (facecnt * 3);
  749.  
  750.     for (facecnt = 0; facecnt < BigShort(facelist->tcount); facecnt++) {
  751.       int j;
  752.       struct mface *actFace = (struct mface *)tmalloc(sizeof(struct mface));
  753.       vec3_t t1, t2, t3;
  754.       float distance;
  755.  
  756.       p0 = edgelist->edges[BigShort(facelist->connects[facecnt][0])][0];
  757.       p1 = edgelist->edges[BigShort(facelist->connects[facecnt][0])][1];
  758.       if ((edgelist->edges[BigShort(facelist->connects[facecnt][1])][0] != p0) &&
  759.       (edgelist->edges[BigShort(facelist->connects[facecnt][1])][0] != p1))
  760.     p2 = edgelist->edges[BigShort(facelist->connects[facecnt][1])][0];
  761.       else
  762.     p2 = edgelist->edges[BigShort(facelist->connects[facecnt][1])][1];
  763.  
  764.       point = &pointlist->points[BigShort(p0)];
  765.       actFace->p0[0] = fract2float(BigLong(point->x));
  766.       actFace->p0[1] = fract2float(BigLong(point->y));
  767.       actFace->p0[2] = fract2float(BigLong(point->z));
  768.       point = &pointlist->points[BigShort(p1)];
  769.       actFace->p1[0] = fract2float(BigLong(point->x));
  770.       actFace->p1[1] = fract2float(BigLong(point->y));
  771.       actFace->p1[2] = fract2float(BigLong(point->z));
  772.       point = &pointlist->points[BigShort(p2)];
  773.       actFace->p2[0] = fract2float(BigLong(point->x));
  774.       actFace->p2[1] = fract2float(BigLong(point->y));
  775.       actFace->p2[2] = fract2float(BigLong(point->z));
  776.  
  777.       /*
  778.        * correct to clockwise order
  779.        * planenormal must direct to other side of middle
  780.        * or: the middle must be in the negative side of the room splitted by the plane
  781.        * positive distance between plane and point mean it is on the positive side
  782.        *
  783.        * Erzeugen der Hessischen Normalenform
  784.        * building of hesse-normalform ? to calculate distane between plane and point
  785.        */
  786.       VectorSubtract(actFace->p0, actFace->p1, t1);
  787.       VectorSubtract(actFace->p2, actFace->p1, t2);
  788.       VectorCopy(actFace->p1, t3);
  789.       CrossProduct(t1, t2, actFace->plane.normal);
  790.       VectorNormalize(actFace->plane.normal);
  791.       actFace->plane.dist = DotProduct(t3, actFace->plane.normal);
  792.  
  793.       if ((distance = DotProduct(middle, actFace->plane.normal) - actFace->plane.dist) > 0) {
  794.     vec3_t temp;
  795.  
  796.     VectorCopy(actFace->p0, temp);
  797.     VectorCopy(actFace->p2, actFace->p0);
  798.     VectorCopy(temp, actFace->p2);
  799.  
  800.     VectorNegate(actFace->plane.normal);
  801.     actFace->plane.dist = -actFace->plane.dist;
  802.       }
  803.  
  804.       /*
  805.        * elimination doubled faces in resulting only valid brushes
  806.        * equal is: if normal and distance to origin are equal
  807.        * the distance to origin is equal then if the angle between normal and normal of ?-normal is equal
  808.        *
  809.        * in theory in quakeMode, there are no eleminations possible
  810.        */
  811.       checkFace = actBrush->faces;
  812.       while (checkFace) {
  813.     float a, b, c;
  814.  
  815.     /* Abstand Punkt->Ebene / distances point->plane */
  816.     a = fabs(DotProduct(actFace->p0, checkFace->plane.normal) - checkFace->plane.dist);
  817.     b = fabs(DotProduct(actFace->p1, checkFace->plane.normal) - checkFace->plane.dist);
  818.     c = fabs(DotProduct(actFace->p2, checkFace->plane.normal) - checkFace->plane.dist);
  819.  
  820.     /* if point->plane less than minimum, eleminate them */
  821.     if ((a < ON_EPSILON) && (b < ON_EPSILON) && (c < ON_EPSILON))
  822.       break;
  823.  
  824.     checkFace = checkFace->next;
  825.       }
  826.  
  827.       if (!checkFace) {
  828.     /*
  829.      * get the textures
  830.      */
  831.     for (i = 0; i < facegroups; i++) {
  832.       for (j = 0; j < BigShort(facegroup[i]->count); j++) {
  833.         if (BigShort(facegroup[i]->facelist[j]) == facecnt)
  834.           break;
  835.       }
  836.       if (j < BigShort(facegroup[i]->count))
  837.         break;
  838.     }
  839.     for (j = 0; j < brushtexs; j++) {
  840.       if (!__strncmp(facegroup[i]->name, brushtex[j]->subgrp, 18))
  841.         break;
  842.     }
  843.     if (j < brushtexs) {
  844.       float zero[2] =
  845.       {0, 0};
  846.       float one[2] =
  847.       {1, 1};
  848.  
  849.       actFace->texinfo = MakeTexinfo(bspMem, brushtex[j]->name, actFace, one, 0, zero);
  850.     }
  851.  
  852.     actFace->next = actBrush->faces;
  853.     actBrush->faces = actFace;
  854.       }
  855.       else
  856.     tfree(actFace);
  857.     }
  858.  
  859.     tfree(facelist);
  860.     tfree(edgelist);
  861.     tfree(pointlist);
  862.     for (i = 0; i < facegroups; i++)
  863.       tfree(facegroup[i]);
  864.     tfree(facegroup);
  865.     for (i = 0; i < brushtexs; i++)
  866.       tfree(brushtex[i]);
  867.     tfree(brushtex);
  868.  
  869.     /*
  870.      * put in brush
  871.      */
  872.     actBrush->next = fillEntity->brushes;
  873.     fillEntity->brushes = actBrush;
  874.     nummapbrushes++;
  875.   }
  876.   else
  877.     eprintf("not enough data to convert brush!\n");
  878. }
  879.  
  880. void pIFFtopMap(__memBase, register struct IFFchunk *IFFroot, register int iterVal)
  881. {
  882.   struct IFFchunk *IFFpart = IFFroot;
  883.  
  884.   while (IFFpart) {
  885.     struct IFFchunk *actIFFpart = IFFpart;
  886.     int indentSpace = iterVal;
  887.  
  888.     while (indentSpace-- > 0) {
  889.       oprintf("  ");
  890.     }
  891.     oprintf("%4s %d bytes\n", (char *)&actIFFpart->type, actIFFpart->size);
  892.  
  893.     switch (BigLong(actIFFpart->type)) {
  894.     /*
  895.      * only toplevel-processing (iter 0)
  896.      */
  897.       case ID_TDDD:
  898.     /*
  899.      * only toplevel-processing (iter 1)
  900.      */
  901.       case ID_OBJ:
  902.     pIFFtopMap(bspMem, actIFFpart->iter, iterVal + 1);
  903.     break;
  904.     /*
  905.      * only toplevel-processing (iter 2)
  906.      */
  907.       case ID_DESC:
  908.     if (iterVal == 2)
  909.       /* the dummy-axis to save the hierarchie to disk */
  910.       pIFFtopMap(bspMem, actIFFpart->iter, iterVal + 1);
  911.     else {
  912.       if (actIFFpart->iter) {
  913.         struct IFFchunk *Brushes = actIFFpart->iter;
  914.         struct entity *thisEntity;
  915.  
  916.         if (bspMem->nummapentities == bspMem->max_nummapentities)
  917.           ExpandClusters(bspMem, MAP_ENTITIES);
  918.         thisEntity = &bspMem->mapentities[bspMem->nummapentities];
  919.         bspMem->nummapentities++;
  920.  
  921.         while (Brushes) {
  922.           if (Brushes->type == BigLong(ID_NAME)) {
  923.         thisEntity->classname = (char *)tmalloc(__strlen(Brushes->data) + 1);
  924.         strlwrcpy(thisEntity->classname, Brushes->data);
  925.           }
  926.           else if (Brushes->type == BigLong(ID_INT1)) {
  927.         struct int1 *inten = (struct int1 *)Brushes->data;
  928.  
  929.         thisEntity->light = (unsigned char)rint((fract2float(BigLong(inten->intensity.x)) +
  930.                              fract2float(BigLong(inten->intensity.y)) +
  931.                              fract2float(BigLong(inten->intensity.z))) / 3);
  932.           }
  933.           else if (Brushes->type == BigLong(ID_SHP2)) {
  934.         struct shap *shape = (struct shap *)Brushes->data;
  935.  
  936.         if ((shape->lamp & BigLong(LP2_TYPE)) != BigLong(LP2_NOLAM))
  937.           thisEntity->style = 1;
  938.           }
  939.           else if (Brushes->type == BigLong(ID_POSI)) {
  940.         struct posi *origin = (struct posi *)Brushes->data;
  941.  
  942.         thisEntity->origin[0] = fract2float(BigLong(origin->position.x));
  943.         thisEntity->origin[1] = fract2float(BigLong(origin->position.y));
  944.         thisEntity->origin[2] = fract2float(BigLong(origin->position.z));
  945.           }
  946.           else if (Brushes->type == BigLong(ID_TXT4)) {
  947.         struct texture4 *brushtex = (struct texture4 *)Brushes->data;
  948.         struct epair *lastString;
  949.         struct epair *actString = (struct epair *)tmalloc(sizeof(struct epair));
  950.  
  951.         actString->next = 0;
  952.         actString->key = (char *)tmalloc(brushtex->length + 1);
  953.         __strncpy(actString->key, brushtex->name, brushtex->length);
  954.         actString->key[brushtex->length] = '\0';
  955.         actString->value = (char *)tmalloc(__strlen(brushtex->label) + 1);
  956.         __strcpy(actString->value, brushtex->label);
  957.  
  958.         if ((lastString = thisEntity->epairs)) {
  959.           while (lastString->next)
  960.             lastString = lastString->next;
  961.           lastString->next = actString;
  962.         }
  963.         else
  964.           thisEntity->epairs = actString;
  965.           }
  966.           else if (Brushes->type == BigLong(ID_DESC)) {
  967.         /*
  968.          * after this we get no datas any more
  969.          */
  970.         if (Brushes->iter)
  971.           pIFFtopBrushes(bspMem, Brushes->iter, iterVal + 1, thisEntity);
  972.           }
  973.           Brushes = Brushes->next;
  974.         }
  975.  
  976.         /*
  977.          * for all 
  978.          */
  979.         if (VectorZero(thisEntity->origin))
  980.           GetVectorForKey(thisEntity, "origin", thisEntity->origin);
  981.         if (!thisEntity->classname)
  982.           thisEntity->classname = ValueForKey(thisEntity, "classname");
  983.         thisEntity->target = ValueForKey(thisEntity, "target");
  984.         thisEntity->targetname = ValueForKey(thisEntity, "targetname");
  985.  
  986.         /*
  987.          * special for qbsp+light+vis in one part 
  988.          */
  989.         if (bspMem->mapOptions & MAP_LOADLIGHTS) {
  990.           if (!(thisEntity->light = FloatForKeyN(thisEntity, "light")))
  991.         if (!(thisEntity->light = FloatForKey(thisEntity, "_light")))
  992.           if (!thisEntity->light)
  993.             thisEntity->light = MAX_MAPLIGHTLEVEL;
  994.           if (!(thisEntity->style = FloatForKey(thisEntity, "style")))
  995.         if (!(thisEntity->style = FloatForKey(thisEntity, "_style")))
  996.           if (!thisEntity->style)
  997.             thisEntity->style = 0;
  998.           if (!thisEntity->angle)
  999.         thisEntity->angle = FloatForKey(thisEntity, "angle");
  1000.  
  1001.           if (__strcmp(thisEntity->classname, "light")) {
  1002.         if (!thisEntity->light)
  1003.           thisEntity->light = DEFAULTLIGHTLEVEL;
  1004.  
  1005.         if (thisEntity->targetname[0] && !thisEntity->style) {
  1006.           char s[256];
  1007.  
  1008.           thisEntity->style = LightStyleForTargetname(thisEntity->targetname, TRUE);
  1009.           sprintf(s, "%i", thisEntity->style);
  1010.           SetKeyValue(thisEntity, "style", s);
  1011.         }
  1012.           }
  1013.         }
  1014.       }
  1015.     }
  1016.     break;
  1017.       default:
  1018.     break;
  1019.     }
  1020.     IFFpart = IFFpart->next;
  1021.     tfree(actIFFpart->data);
  1022.     tfree(actIFFpart);
  1023.   }
  1024. }
  1025.  
  1026. /*
  1027.  * the rules:
  1028.  * 
  1029.  * -the hierarchy:
  1030.  * 
  1031.  * DESC "world/axis/root" (axis)
  1032.  * -> acts as global group-manager to save all subhierarchies
  1033.  * DESC "worldspawn" (axis)
  1034.  * -> all subdesc's desribes the brushes (objects grouped to axis "worldspawn")
  1035.  * -> all subdesc's texture info must contain the name of the texture to use and
  1036.  * the alignment/positioning must be valid
  1037.  * DESC "info_player_start" (axis)
  1038.  * -> the axis position describes the players origin
  1039.  * DESC "standard quake"
  1040.  * -> will be searched for information
  1041.  * (eg. DESC "light" (axis with light) is the standard entity "light", parameters
  1042.  * are parsed out of the axis-informations)
  1043.  * -> axis that are groupt to a non-worldspawn-entity and that have no brushes
  1044.  * will beinterpreted as movement-points (?)
  1045.  * -> the texture-list of an entity will be parsed for key-values (standard-quake
  1046.  * like "target")
  1047.  * 
  1048.  * restriction: 
  1049.  * 
  1050.  * dont make objects, that are not convex
  1051.  * calculation of clockwise point-order goes via middlepoint of object
  1052.  * 
  1053.  */
  1054.  
  1055. /*
  1056.  * ================
  1057.  * SaveTDDDFile
  1058.  * ================
  1059.  */
  1060. bool SaveTDDDFile(__memBase, HANDLE outFile)
  1061. {
  1062.   struct entity *ent;
  1063.   struct epair *ep;
  1064.   struct mbrush *b;
  1065.   struct mface *f;
  1066.   int i;
  1067.   struct dmiptexlump_t *head_miptex = (struct dmiptexlump_t *)bspMem->shared.quake1.dtexdata;
  1068.   int lastTDDD = 0;
  1069.   int lastObj = 0;
  1070.   int lastWorld = 0;
  1071.   int lastRoot = 0;
  1072.   int lastDesc = 0;
  1073.  
  1074.   /*
  1075.    * hierarchy:
  1076.    * 
  1077.    * TDDD
  1078.    * OBJ
  1079.    * DESC         worldaxis
  1080.    * | DESC        worldspawn
  1081.    * | | DESC   model1
  1082.    * | | +-TOBJ
  1083.    * | | DESC   model2
  1084.    * | | +-TOBJ
  1085.    * | | ...
  1086.    * | +-TOBJ
  1087.    * | DESC        light
  1088.    * | ...
  1089.    * +-TOBJ
  1090.    */
  1091.  
  1092.   SetForm(outFile, &lastTDDD, ID_TDDD);
  1093.   SetRoot(outFile, &lastObj, ID_OBJ);
  1094.  
  1095.   SetRoot(outFile, &lastWorld, ID_DESC);
  1096.   SetClassName(outFile, "worldaxis");
  1097.   SetOtherDefaults(outFile, 0);
  1098.   VerRoot(outFile, &lastWorld, ID_DESC);
  1099.  
  1100.   /* set worldspawn as root of all the other models */
  1101.   SetRoot(outFile, &lastRoot, ID_DESC);
  1102.   for (i = 0, ent = bspMem->mapentities; i < bspMem->nummapentities; i++, ent++)
  1103.     if (!__strcmp(ent->classname, "worldspawn"))
  1104.       break;
  1105.  
  1106.   if (i == bspMem->nummapentities) {
  1107.     eprintf("SaveTDDDFile: worldspawn not found!\n");
  1108.     return FALSE;
  1109.   }
  1110.  
  1111.   SetClassName(outFile, ent->classname);
  1112.   for (ep = ent->epairs; ep; ep = ep->next)
  1113.     if (__strcmp(ep->key, "model"))
  1114.       SetEntity(outFile, ep->key, ep->value);
  1115.   for (b = ent->brushes; b; b = b->next) {
  1116.     for (f = b->faces; f; f = f->next) {
  1117.       struct texinfo *texinfo = &bspMem->shared.quake1.texinfo[f->texinfo];
  1118.       char *miptexname;
  1119.  
  1120.       if (head_miptex)                        /* for an allready compiled map */
  1121.     miptexname = ((struct mipmap *)(bspMem->shared.quake1.dtexdata + head_miptex->dataofs[texinfo->miptex]))->name;
  1122.       else if (bspMem->maptexstrings)                /* for an uncompiled map */
  1123.     miptexname = bspMem->maptexstrings[texinfo->miptex];
  1124.       else                            /* for unknown states */
  1125.     miptexname = "unknown\0";
  1126.  
  1127.       SaveFace(f->p0, f->p1, f->p2, miptexname);
  1128.     }
  1129.   }
  1130.   SetPoints(outFile);
  1131.   SetEdges(outFile);
  1132.   SetFaces(outFile);
  1133.   SetBrushes(outFile);
  1134.   SetOtherDefaults(outFile, ent);
  1135.   VerRoot(outFile, &lastRoot, ID_DESC);
  1136.  
  1137.   for (i = 0, ent = bspMem->mapentities; i < bspMem->nummapentities; i++, ent++) {
  1138.     bool model = FALSE;
  1139.  
  1140.     for (ep = ent->epairs; ep; ep = ep->next) {
  1141.       if (!__strcmp(ep->key, "model")) {
  1142.     model = TRUE;
  1143.     break;
  1144.       }
  1145.     }
  1146.  
  1147.     if (model && __strcmp(ent->classname, "worldspawn")) {
  1148.       SetRoot(outFile, &lastDesc, ID_DESC);
  1149.       SetClassName(outFile, ent->classname);
  1150.       for (ep = ent->epairs; ep; ep = ep->next)
  1151.     if (__strcmp(ep->key, "model"))
  1152.       SetEntity(outFile, ep->key, ep->value);
  1153.       for (b = ent->brushes; b; b = b->next) {
  1154.     for (f = b->faces; f; f = f->next) {
  1155.       struct texinfo *texinfo = &bspMem->shared.quake1.texinfo[f->texinfo];
  1156.       char *miptexname;
  1157.  
  1158.       if (head_miptex)                    /* for an allready compiled map */
  1159.         miptexname = ((struct mipmap *)(bspMem->shared.quake1.dtexdata + head_miptex->dataofs[texinfo->miptex]))->name;
  1160.       else if (bspMem->maptexstrings)            /* for an uncompiled map */
  1161.         miptexname = bspMem->maptexstrings[texinfo->miptex];
  1162.       else                            /* for unknown states */
  1163.         miptexname = "unknown\0";
  1164.  
  1165.       SaveFace(f->p0, f->p1, f->p2, miptexname);
  1166.     }
  1167.       }
  1168.       SetPoints(outFile);
  1169.       SetEdges(outFile);
  1170.       SetFaces(outFile);
  1171.       SetBrushes(outFile);
  1172.       SetOtherDefaults(outFile, ent);
  1173.       VerRoot(outFile, &lastDesc, ID_DESC);
  1174.       SetEndM(outFile, ID_TOBJ);
  1175.     }
  1176.   }
  1177.   SetEndM(outFile, ID_TOBJ);
  1178.   VerRoot(outFile, &lastObj, ID_OBJ);
  1179.   VerRoot(outFile, &lastTDDD, ID_FORM);
  1180.  
  1181.   mprintf("----- SaveTDDDFile -------\n");
  1182.   mprintf("%5i points\n", TDDDnumpoints);
  1183.   mprintf("%5i edges\n", TDDDnumedges);
  1184.   mprintf("%5i faces\n", TDDDnumfaces);
  1185.   mprintf("%5i groups\n", TDDDnumgroups);
  1186.   mprintf("%5i objects\n", TDDDnumobjects);
  1187.  
  1188.   return TRUE;
  1189. }
  1190.  
  1191. /*
  1192.  * ================
  1193.  * LoadTDDDFile
  1194.  * ================
  1195.  */
  1196. bool LoadTDDDFile(__memBase, unsigned char *tdddBuf)
  1197. {
  1198.   struct IFFheader IFFfile =
  1199.   {0, 0, 0};
  1200.   struct IFFchunk *IFFroot = (struct IFFchunk *)tmalloc(sizeof(struct IFFchunk));
  1201.  
  1202.   __memcpy(&IFFfile, tdddBuf, 12);
  1203.   tdddBuf += 12;
  1204.   IFFroot->type = IFFfile.type;
  1205.   IFFroot->size = IFFfile.size - 4;
  1206.   IFFroot->next = 0;
  1207.   IFFroot->iter = 0;
  1208.   IFFroot->data = 0;
  1209.   memIFFtopIFF(tdddBuf, IFFroot);
  1210.   pIFFtopMap(bspMem, IFFroot, 0);
  1211.   MatchTargets(bspMem);
  1212.  
  1213.   mprintf("----- LoadTDDDFile -------\n");
  1214.   mprintf("%5i brushes\n", nummapbrushes);
  1215.   mprintf("%5i entities\n", bspMem->nummapentities);
  1216.   mprintf("%5i miptex\n", bspMem->nummaptexstrings);
  1217.   mprintf("%5i texinfo\n", bspMem->shared.quake1.numtexinfo);
  1218.  
  1219.   return TRUE;
  1220. }
  1221.